package com.dongdongshop.service.impl;

import com.alibaba.dubbo.config.annotation.Service;
import com.dongdongshop.front.pojo.TbUser;
import com.dongdongshop.front.pojo.TbUserExample;
import com.dongdongshop.front.service.UserService;
import com.dongdongshop.mapper.TbUserMapper;
import com.dongdongshop.utils.HttpClientUtil;
import com.dongdongshop_util.JavaMailUtil;
import com.dongdongshop_util.ShiroUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

@Component
@Service
@Transactional
public class UserServiceImpl implements UserService {

    @Autowired
    private TbUserMapper userMapper;
    @Autowired
    private RedisTemplate redisTemplate;

    @Override
    public TbUser getUserByName(String name) {
        TbUser user = userMapper.getUserByName(name);
        return user;
    }

    @Override
    public void addUser(TbUser tbUser) {
        userMapper.insertSelective(tbUser);
    }

    @Override
    public List<TbUser> getAll() {
        return userMapper.selectByExample(new TbUserExample());
    }

    @Override
    public void resetPwd(Long userId, String mail) {
        TbUser user =  userMapper.selectByPrimaryKey(userId);

        String pwd = String.valueOf(Math.random()).substring(2,8);
        String message = "您新的密碼為: "+pwd +"  ，請您妥善保管.";
        String title = "重置密碼";

        System.err.println("新生成的密碼為： {}"+pwd);

        boolean b = JavaMailUtil.useTencent(mail, title, message);

        String md5Password = ShiroUtils.encryptPassword("MD5", pwd, "90aa5a", 10);
        user.setEmail(mail);
        user.setPassword(md5Password);
        user.setUpdated(Date.from(LocalDateTime.now().atZone(ZoneId.systemDefault()).toInstant()));
        userMapper.updateByPrimaryKeySelective(user);
    }

    /* 使用httpClient发送短信验证码 */
    @Override
    public void sendVerify(String phone) throws Exception {

        String accessKeyId = "LTAI4G64FQi4fg7X94gJnCS8";
        String accessKeySecret = "JW6adh0hkOWgERxATyjaILbt2Oc3UD";
        java.text.SimpleDateFormat df = new java.text.SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
        df.setTimeZone(new java.util.SimpleTimeZone(0, "GMT"));// 这里一定要设置GMT时区
        java.util.Map<String, String> paras = new java.util.HashMap<String, String>();
        // 1. 系统参数
        paras.put("SignatureMethod", "HMAC-SHA1");
        paras.put("SignatureNonce", java.util.UUID.randomUUID().toString());
        paras.put("AccessKeyId", accessKeyId);
        paras.put("SignatureVersion", "1.0");
        paras.put("Timestamp", df.format(new java.util.Date()));
        paras.put("Format", "XML");
        // 2. 业务API参数
        paras.put("Action", "SendSms");
        paras.put("Version", "2017-05-25");
        paras.put("RegionId", "cn-hangzhou");
        paras.put("PhoneNumbers", phone);
        paras.put("SignName", "尾巴");
        String verify = String.valueOf(Math.random()).substring(2,8);
        paras.put("TemplateParam", "{\"sms_code\":"+verify+"}");
        paras.put("TemplateCode", "SMS_189760467");
        paras.put("OutId", "123");
        // 3. 去除签名关键字Key
        if (paras.containsKey("Signature"))
            paras.remove("Signature");
        // 4. 参数KEY排序
        java.util.TreeMap<String, String> sortParas = new java.util.TreeMap<String, String>();
        sortParas.putAll(paras);
        // 5. 构造待签名的字符串
        java.util.Iterator<String> it = sortParas.keySet().iterator();
        StringBuilder sortQueryStringTmp = new StringBuilder();
        while (it.hasNext()) {
            String key = it.next();
            sortQueryStringTmp.append("&").append(specialUrlEncode(key)).append("=").append(specialUrlEncode(paras.get(key)));
        }
        String sortedQueryString = sortQueryStringTmp.substring(1);// 去除第一个多余的&符号
        StringBuilder stringToSign = new StringBuilder();
        stringToSign.append("GET").append("&");
        stringToSign.append(specialUrlEncode("/")).append("&");
        stringToSign.append(specialUrlEncode(sortedQueryString));
        String sign = sign(accessKeySecret + "&", stringToSign.toString());
        // 6. 签名最后也要做特殊URL编码
        String signature = specialUrlEncode(sign);
        System.out.println(paras.get("SignatureNonce"));
        System.out.println("\r\n=========\r\n");
        System.out.println(paras.get("Timestamp"));
        System.out.println("\r\n=========\r\n");
        System.out.println(sortedQueryString);
        System.out.println("\r\n=========\r\n");
        System.out.println(stringToSign.toString());
        System.out.println("\r\n=========\r\n");
        System.out.println(sign);
        System.out.println("\r\n=========\r\n");
        System.out.println(signature);
        System.out.println("\r\n=========\r\n");
        // 最终打印出合法GET请求的URL
        System.out.println("http://dysmsapi.aliyuncs.com/?Signature=" + signature + sortQueryStringTmp);

        /* httpclient调用接口发送信息 */
        Map<String,String> map = new HashMap<>();
        HttpClientUtil.doGet("http://dysmsapi.aliyuncs.com/?Signature=" + signature + sortQueryStringTmp, map, "utf-8");

        System.err.println("系統生成的短信验证码为："+verify);

        /* 将验证码以手机号为key放入redis */
        redisTemplate.boundValueOps(phone).set(verify);

        /* 设置超时时间 */
        redisTemplate.expire(phone,30, TimeUnit.MINUTES);

        return;

    }

    @Override
    public TbUser checkPhoneNum(String telphone) {
        TbUser user = userMapper.checkPhoneNum(telphone);
        return user;
    }

    public static String specialUrlEncode(String value) throws Exception {
        return java.net.URLEncoder.encode(value, "UTF-8").replace("+", "%20").replace("*", "%2A").replace("%7E", "~");
    }
    public static String sign(String accessSecret, String stringToSign) throws Exception {
        javax.crypto.Mac mac = javax.crypto.Mac.getInstance("HmacSHA1");
        mac.init(new javax.crypto.spec.SecretKeySpec(accessSecret.getBytes("UTF-8"), "HmacSHA1"));
        byte[] signData = mac.doFinal(stringToSign.getBytes("UTF-8"));
        return new sun.misc.BASE64Encoder().encode(signData);
    }
}
